#!/usr/bin/env perl 
use warnings;
use strict;
use Getopt::Long;
eval {
  require GraphViz::Parse::Yapp;
};

die "Install GraphViz:\n\$ cpan GraphViz\n" if $@;

my $tree = undef;
my $format = '';

GetOptions (
  "format=s"  => \$format,
  "help"    => \&usage,
  "tree=s"  => \$tree,
);

if (defined($tree)) {
  $format = 'text' unless defined($format);
  processTree(@ARGV);
}
else {
  $format = 'png' unless defined($format);
  processGrammar(@ARGV);
}

sub processGrammar {

  error("Unknown format") unless $format =~ m{
                               ^(
                                png|ps|text|gif|jpeg|
                                wbmp|cmapx|cmap|ismap|imap|
                                vrml|vtx|mp|fig|svg|svgz|plain|
                                canon|debug|hpgl|pcl|mif|pic|gd
                                )$
                              }x;
  my $file = shift || error("Provide a .output file");

  $file =~ s/\.(output|eyp|yp)$//;
  error("Cant find file $file.output") unless -r "$file.output" || -r "$file.eyp" || -r "$file.yp";

  unless (-r "$file.output") {
          eval {
            require Parse::Eyapp;
          };
          die "Install Parse::Eyapp or Parse::Yapp\n" if $@;

          my $gf = -r "$file.eyp" ? "$file.eyp" : "$file.yp";
          my($parser)=new Parse::Eyapp(inputfile => $gf);
          my($warnings)=$parser->Warnings();
                  $warnings
          and print STDERR $warnings;
          $parser->outputtables("", $file);
  }

  my $method = "as_$format";
  my $g = GraphViz::Parse::Yapp->new("$file.output");

  $g->$method("$file.$format");
}

sub processTree {
  
  my $file = shift;

  eval {
    require Text::Tree;
  };
  die "Install Text::Tree:\n\$ cpan Text::Tree\n" if $@;

  eval {
    require Parse::Eyapp::Node;
  };
  die "Install Parse::Eyapp::Node\n" if $@;

  my $blesser = sub {
    my $class = shift;
    my @children = @_;

    [$class, @children];
  };

  my $t;
  {
    package Parse::Eyapp::Node;
    $t = _new($blesser, '', $tree);
  }

  my $tt = Text::Tree->new(@$t);

  if (defined($file)) {
    open my $f, "> $file" or die "Can't open $file\n";

    print $f $tt->layout('boxed');

    close($f);
  }
  else {
    print $tt->layout('boxed');
  }

}

sub error {
  my $message = shift;

  print "$message\n" if $message;
  usage();
}

sub usage {
  print << "HELP";
Usage: 
            $0 [-f format ] filename
or
            $0 -t 'node1(ch1, ch2(ch3, ch4))

Format is one of:
  png
  ps
  text
  gif
  jpeg
  s_wbmp
  cmapx
  cmap
  ismap
  imap
  vrml
  vtx
  mp
  fig
  svg
  svgz
  plain
  canon
  debug
  hpgl
  pcl
  mif
  pic
  gd
HELP
  exit(1);
}

=head1 NAME

vgg - Produces a graph for a Eyapp grammar or a tree term


=head1 SYNOPSYS

  # for tree terms
  vgg -t 'Operator(LeftBinaryOp(expr,term),RightBinaryOp(power),PreUnaryOp(uneg),PostUnaryOp(factorial))'  # dump to stdout
  vgg -t 'Operator(LeftBinaryOp(expr,term),RightBinaryOp(power),PreUnaryOp(uneg),PostUnaryOp(factorial))' tree.txt

  # for grammars
  vgg Calc
  vgg Calc.output
  vgg -f ps Calc
  vgg I<-h>

=head1 INSTALL

For this script to work, you have to install L<GraphViz> and L<Text::Tree> first

=head1 EXAMPLE

Here is an example of use:

    $ vgg -t 'Operator(LeftBinaryOp(expr,term),RightBinaryOp(power),PreUnaryOp(uneg),PostUnaryOp(factorial))'
                           +--------+
                           |Operator|
                           +--------+
          .---------------.----^--------.-------------.
    +------------+ +-------------+ +----------+ +-----------+
    |LeftBinaryOp| |RightBinaryOp| |PreUnaryOp| |PostUnaryOp|
    +------------+ +-------------+ +----------+ +-----------+
      .---^--.        |              |               |
    +----+ +----+  +-----+         +----+       +---------+
    |expr| |term|  |power|         |uneg|       |factorial|
    +----+ +----+  +-----+         +----+       +---------+

=head1 SEE ALSO

=over

=item * L<GraphViz>

=item * L<Text::Tree>

=item * L<eyapp>,

=item * The pdf file in L<http://nereida.deioc.ull.es/~pl/perlexamples/Eyapp.pdf> 

=back

=head1 ACKNOWLEDGMENTS

This work has been supported by CEE (FEDER) and the Spanish Ministry of
I<Educacion y Ciencia> through I<Plan Nacional I+D+I> number TIN2005-08818-C04-04
(ULL::OPLINK project L<http://www.oplink.ull.es/>). 
Support from Gobierno de Canarias was through GC02210601
(I<Grupos Consolidados>).
The University of La Laguna has also supported my work in many ways
and for many years.

I wish to thank Leon Brocard for his L<GraphViz::Parse::Yacc> module.


=head1 AUTHOR

Casiano Rodriguez-Leon 

=head1 COPYRIGHT

(c) Copyright 2006 Casiano Rodriguez-Leon

This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself, either Perl version 5.8.8 or,
at your option, any later version of Perl 5 you may have available.

=cut

